package com.insight.modules.util;

import net.sourceforge.pinyin4j.PinyinHelper;

import java.io.UnsupportedEncodingException;

/**
 * @author wangruheng
 * @title: ChineseCharToEnUtil
 * @projectName insight-control-parent
 * @description: TODO
 * @date 2020/11/16-15:01
 */
public class ChineseCharToEnUtil {

    /**
     * 汉字区位码对应的起始区间值数组，用于判断汉字的声母区间
     * 这些数字表示GB2312编码中的区位码起点
     */
    private final static int[] li_SecPosValue = {
            1601, 1637, 1833, 2078, 2274,
            2302, 2433, 2594, 2787, 3106,
            3212, 3472, 3635, 3722, 3730,
            3858, 4027, 4086, 4390, 4558,
            4684, 4925, 5249, 5590
    };

    /**
     * 汉字首字母对应表，跟区位码对应，去掉了不常用的i, u, v声母
     */
    private final static String[] lc_FirstLetter = {
            "a", "b", "c", "d", "e",
            "f", "g", "h", "j", "k",
            "l", "m", "n", "o", "p",
            "q", "r", "s", "t", "w",
            "x", "y", "z"
    };

    /**
     * 取得字符串中每个汉字的首字母拼接成字符串（声母串）
     * @param str 需要转换的汉字字符串
     * @return 拼接后的首字母字符串，如果传入为空返回空串
     */
    public String getAllFirstLetter(String str) {
        if (str == null || str.trim().length() == 0) {
            return "";
        }
        String result = "";
        // 遍历字符串，每次获取一个字符的首字母，拼接结果
        for (int i = 0; i < str.length(); i++) {
            result += this.getFirstLetter(str.substring(i, i + 1));
        }
        return result;
    }

    /**
     * 获取单个汉字的首字母
     * @param chinese 传入单个汉字字符串
     * @return 返回对应的首字母字符串（小写）
     */
    public String getFirstLetter(String chinese) {
        if (chinese == null || chinese.trim().length() == 0) {
            return "";
        }
        // 将字符串编码从GB2312转换为ISO8859-1，方便取区位码
        chinese = this.conversionStr(chinese, "GB2312", "ISO8859-1");

        if (chinese.length() > 1) { // 是汉字（两个字节）
            int li_SectorCode = (int) chinese.charAt(0) - 160; // 计算区码
            int li_PositionCode = (int) chinese.charAt(1) - 160; // 计算位码
            int li_SecPosCode = li_SectorCode * 100 + li_PositionCode; // 区位码

            // 根据区位码判断首字母区间
            if (li_SecPosCode > 1600 && li_SecPosCode < 5590) {
                for (int i = 0; i < 23; i++) {
                    // 找出落在哪个区间，就对应那个首字母
                    if (li_SecPosCode >= li_SecPosValue[i] && li_SecPosCode < li_SecPosValue[i + 1]) {
                        chinese = lc_FirstLetter[i];
                        break;
                    }
                }
            } else {
                // 不是标准汉字，转回GB2312编码，再取第一个字符
                chinese = this.conversionStr(chinese, "ISO8859-1", "GB2312");
                chinese = chinese.substring(0, 1);
            }
        }
        return chinese;
    }

    /**
     * 字符串编码转换
     * @param str 待转换的字符串
     * @param charsetName 原编码字符集名称
     * @param toCharsetName 目标编码字符集名称
     * @return 转换编码后的字符串，异常时原样返回
     */
    private String conversionStr(String str, String charsetName, String toCharsetName) {
        try {
            // 先将字符串转成字节数组，再用目标编码解析成字符串
            str = new String(str.getBytes(charsetName), toCharsetName);
        } catch (UnsupportedEncodingException ex) {
            System.out.println("字符串编码转换异常：" + ex.getMessage());
        }
        return str;
    }

    /**
     * 获取字符串的拼音首字母大写缩写（依赖pinyin4j库）
     * 例如 "中国" -> "ZG"
     * @param str 需要转换的中文字符串
     * @return 拼音首字母大写字符串，如果不是汉字原样返回
     */
    public static String getPinYinHeadChar(String str) {
        StringBuilder convert = new StringBuilder();
        for (int j = 0; j < str.length(); j++) {
            char word = str.charAt(j);
            // 获取该字符的拼音数组，可能有多音字，取第一个拼音
            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
            if (pinyinArray != null) {
                // 取第一个拼音的首字母
                convert.append(pinyinArray[0].charAt(0));
            } else {
                // 非汉字，直接拼接字符
                convert.append(word);
            }
        }
        // 转成大写返回
        return convert.toString().toUpperCase();
    }
}
